const std = @import("std");
const buildin = @import("builtin");

//本程序主要作用是用于将yazi的配置文件复制到系统
//WINKIT终端本来经已将所有环境变量重定位到自身目录，
//但由于yazi可能在其代码中写死了固定的配置路径，
//并未在所有地方都统一使用环境变量拼接路径，
//导致WINKIT即使重置了环境变量指向自己亦未能使之正常读取我们自己目录内的配置，
//所以，方有此程序，每次在终端输入「y」即可调用y.cmd来启动有正确配置的yazi。

pub fn main() !void {
    const allocator = std.heap.page_allocator;

    //获取 WINKIT_HOME 环境变量
    var winkit_home: []u8 = undefined;
    if (std.process.getEnvVarOwned(allocator, "WINKIT_HOME")) |env_var| {
        winkit_home = env_var;
    } else |_| {
        var self_program_path_buf: [std.fs.max_path_bytes]u16 = undefined;
        const result = std.os.windows.GetModuleFileNameW(null, &self_program_path_buf, @intCast(self_program_path_buf.len));

        if (result) |self_program_path_slice| {
            const self_program_path_wide = self_program_path_slice;

            const self_program_path_utf8 = std.unicode.utf16LeToUtf8Alloc(allocator, self_program_path_wide) catch |err| {
                std.debug.print("Failed to convert path to utf8:{}\n", .{err});
                return err;
            };
            defer allocator.free(self_program_path_utf8);

            const parent_dir = std.fs.path.dirname(self_program_path_utf8) orelse ".";
            const grandparent_dir = std.fs.path.dirname(parent_dir) orelse ".";

            winkit_home = try std.fmt.allocPrint(allocator, "{s}", .{grandparent_dir});
            defer allocator.free(winkit_home);
        } else |err| {
            std.debug.print("Failed to get module file name:{}\n", .{err});
            return err;
        }
    }

    // 获取 APPDATA 环境变量
    // echo %AppData%
    // C:\Users\Administrator\AppData\Roaming
    const appdata = std.process.getEnvVarOwned(allocator, "APPDATA") catch |err| {
        std.debug.print("Failed to get APPDATA environment variable:{}\n", .{err});
        return err;
    };
    defer allocator.free(appdata);

    //构建源文件路径同目标文件路径
    const source_path = try std.fmt.allocPrint(allocator, "{s}\\share\\yazi-x86_64-pc-windows-msvc\\yazi.toml", .{winkit_home});
    defer allocator.free(source_path);

    const dest_path = try std.fmt.allocPrint(allocator, "{s}\\yazi\\config\\yazi.toml", .{appdata});
    defer allocator.free(dest_path);

    //若不存在，则创建目标目录（使用绝对路径）
    _ = std.fs.makeDirAbsolute(std.fs.path.dirname(dest_path).?) catch |err| {
        if (err != error.PathAlreadyExists) return err;
        // 目录已存在，忽略错误
    };

    //const src_file = try std.fs.openFileAbsolute(source_path, .{ .mode = .read_only });
    //defer src_file.close();

    // const dst_file = try std.fs.createFileAbsolute(dest_path, .{});
    // defer dst_file.close();

    // var buffer: [1024]u8 = undefined;
    // while (true) {
    //     const bytes_read = try src_file.read(&buffer);
    //     if (bytes_read == 0) break;
    //     _ = try dst_file.write(buffer[0..bytes_read]);
    //}

    //复制文件到当前用户的APPDATA目录
    const source_path_formatted = try replaceBackslashes(allocator, source_path);
    defer allocator.free(source_path_formatted);
    const dest_path_formatted = try replaceBackslashes(allocator, dest_path);
    defer allocator.free(dest_path_formatted);

    //std.debug.print("s:{s}\n", .{source_path_formatted});
    //std.debug.print("d:{s}\n", .{dest_path_formatted});
    try std.fs.copyFileAbsolute(source_path, dest_path, .{});

    // 创建 keymap.toml 文件
    const keymap_dest_path = try std.fmt.allocPrint(allocator, "{s}\\yazi\\config\\keymap.toml", .{appdata});
    defer allocator.free(keymap_dest_path);
    try createKeymapFile(allocator, winkit_home, keymap_dest_path);

    // 获取所有用户并为每个用户复制配置文件
    var all_usernames = try getAllUsernames(allocator);
    defer {
        // 释放用户名列表中的每个用户名
        for (all_usernames.items) |username| {
            allocator.free(username);
        }
        // 释放ArrayList本身
        all_usernames.deinit(allocator);
    }

    //std.debug.print("找到 {d} 个用户，正在为每个用户复制配置文件...\n", .{all_usernames.items.len});

    // 为每个用户复制配置文件
    for (all_usernames.items) |username| {
        // 构建用户的目标路径：C:\Users\<用户名>\AppData\Roaming\yazi\config\yazi.toml
        const user_dest_path = try std.fmt.allocPrint(allocator, "C:\\Users\\{s}\\AppData\\Roaming\\yazi\\config\\yazi.toml", .{username});
        defer allocator.free(user_dest_path);

        // 格式化路径用于打印
        const user_dest_path_formatted = try replaceBackslashes(allocator, user_dest_path);
        defer allocator.free(user_dest_path_formatted);

        //std.debug.print("正在为用户 {s} 复制到: {s}\n", .{username, user_dest_path_formatted});

        // 确保目标目录存在（使用绝对路径）
        _ = std.fs.makeDirAbsolute(std.fs.path.dirname(user_dest_path).?) catch |err| {
            if (err != error.PathAlreadyExists) return err;
            // 目录已存在，忽略错误
        };

        // 复制文件
        try std.fs.copyFileAbsolute(source_path, user_dest_path, .{});

        // 创建 keymap.toml 文件
        const user_keymap_dest_path = try std.fmt.allocPrint(allocator, "C:\\Users\\{s}\\AppData\\Roaming\\yazi\\config\\keymap.toml", .{username});
        defer allocator.free(user_keymap_dest_path);
        try createKeymapFile(allocator, winkit_home, user_keymap_dest_path);
    }

    //std.debug.print("所有用户的配置文件复制完成！\n", .{});
}

// 将路径中的反斜杠替换为正斜杠（Zig 0.15.1 兼容版）
pub fn replaceBackslashes(allocator: std.mem.Allocator, path: []const u8) ![]u8 {
    var new_path = std.ArrayList(u8).initCapacity(allocator, path.len) catch |err| {
        return err;
    };

    for (path) |char| {
        if (char == '\\') {
            try new_path.append(allocator, '/');
        } else {
            try new_path.append(allocator, char);
        }
    }

    return new_path.toOwnedSlice(allocator);
}

// 获取当前Windows系统的所有非系统用户名
// 遍历C:\Users目录下的第一级目录，返回所有非系统用户的用户名列表
pub fn getAllUsernames(allocator: std.mem.Allocator) !std.ArrayList([]u8) {
    const users_dir = "C:\\Users";

    var dir = try std.fs.openDirAbsolute(users_dir, .{ .iterate = true });
    defer dir.close();

    var it = dir.iterate();

    // 创建一个ArrayList来存储所有用户名
    var usernames = std.ArrayList([]u8).initCapacity(allocator, 10) catch |err| {
        return err;
    };

    // 系统用户目录列表，这些目录我们需要排除
    const system_dirs = [_][]const u8{ "Public", "Default", "Default User", "All Users", "Default.migrated", "DefaultAppPool", "NetworkService", "LocalService" };

    while (try it.next()) |entry| {
        if (entry.kind != .directory) continue;

        // 检查是否是系统目录
        var is_system_dir = false;
        for (system_dirs) |system_dir| {
            if (std.mem.eql(u8, entry.name, system_dir)) {
                is_system_dir = true;
                break;
            }
        }

        // 跳过系统目录和隐藏目录
        if (is_system_dir or entry.name[0] == '.') continue;

        // 将用户名添加到列表中
        try usernames.append(allocator, try allocator.dupe(u8, entry.name));
    }

    return usernames;
}

// 获取当前Windows系统的用户名
// 遍历C:\Users目录下的第一级目录，返回非系统用户的用户名（如Administrator）
pub fn getCurrentUsername(allocator: std.mem.Allocator) ![]u8 {
    const users_dir = "C:\\Users";

    var dir = try std.fs.openDirAbsolute(users_dir, .{ .iterate = true });
    defer dir.close();

    var it = dir.iterate();

    // 系统用户目录列表，这些目录我们需要排除
    const system_dirs = [_][]const u8{ "Public", "Default", "Default User", "All Users", "Default.migrated" };

    while (try it.next()) |entry| {
        if (entry.kind != .directory) continue;

        // 检查是否是系统目录
        var is_system_dir = false;
        for (system_dirs) |system_dir| {
            if (std.mem.eql(u8, entry.name, system_dir)) {
                is_system_dir = true;
                break;
            }
        }

        // 跳过系统目录和隐藏目录
        if (is_system_dir or entry.name[0] == '.') continue;

        // 返回找到的第一个非系统用户目录名称
        return try allocator.dupe(u8, entry.name);
    }

    // 如果未有找到合适的用户目录，返回错误
    return error.NoUserFound;
}

// 创建 keymap.toml 配置文件
// 参数1: winkit_home - WINKIT_HOME 环境变量的值
// 参数2: target_path - 目标文件路径
pub fn createKeymapFile(allocator: std.mem.Allocator, winkit_home: []const u8, target_path: []const u8) !void {
    //std.debug.print("[createKeymapFile] 开始创建 keymap.toml 文件\n", .{});
    //std.debug.print("[createKeymapFile] winkit_home: {s}\n", .{winkit_home});
    //std.debug.print("[createKeymapFile] 目标路径: {s}\n", .{target_path});

    // 获取目录路径
    const target_dir = std.fs.path.dirname(target_path) orelse {
        std.debug.print("[createKeymapFile] 错误: 无法获取目标文件的目录路径\n", .{});
        return error.InvalidPath;
    };
    //std.debug.print("[createKeymapFile] 目标目录: {s}\n", .{target_dir});

    // 构建 sh.exe 的完整路径
    const sh_exe_path = try std.fmt.allocPrint(allocator, "{s}/bin/sh.exe", .{winkit_home});
    defer allocator.free(sh_exe_path);
    //std.debug.print("[createKeymapFile] sh.exe 路径: {s}\n", .{sh_exe_path});

    // 构建 keymap.toml 内容
    const keymap_content = try std.fmt.allocPrint(allocator, "[[mgr.prepend_keymap]]\non   = \"!\"\nfor  = \"windows\"\nrun  = 'shell \"{s} -l\" --block'\ndesc = \"Open WinKit Terminal here\"", .{sh_exe_path});
    defer allocator.free(keymap_content);

    // 确保目标目录存在（使用绝对路径）
    _ = std.fs.makeDirAbsolute(target_dir) catch |err| {
        if (err != error.PathAlreadyExists) {
            std.debug.print("[createKeymapFile] 创建目录失败: {s}, 错误: {}", .{ target_dir, err });
            return err;
        }
    };

    // 写入文件
    const file = std.fs.createFileAbsolute(target_path, .{}) catch |err| {
        std.debug.print("[createKeymapFile] 创建文件失败: {s}, 错误: {}", .{ target_path, err });
        return err;
    };
    defer file.close();

    _ = file.writeAll(keymap_content) catch |err| {
        std.debug.print("[createKeymapFile] 写入文件内容失败: {s}, 错误: {}", .{ target_path, err });
        return err;
    };

    //std.debug.print("[createKeymapFile] keymap.toml 文件创建成功: {s}\n", .{target_path});
}
